/* default way to create catch2's main */
// #define CATCH_CONFIG_MAIN
// #include <catch2/catch_all.hpp>

/* supplying one's own main for extra options */
#define CATCH_CONFIG_RUNNER
#include <catch2/catch_all.hpp>
#include "catch2_testDir.hpp"
#include "logger.hpp"
#include <filesystem>
#include <iostream>


namespace globalVar
{

/* definition here, declaration in catch2_testDir.hpp". And it's only ever
 * changed from within catch's main. */
std::string testDir {};

} // namespace globalVar

namespace fs = std::filesystem;

bool testDirFound( const fs::path& currentPath ){
	fs::path parent { currentPath.parent_path() };

	auto check = [&]()
		-> bool
	{
		fs::path candidate { parent.parent_path() };
		candidate /= "tests";
		if ( fs::is_directory(candidate) ){
			globalVar::testDir = candidate.string();
			return true;
		}
		return false;
	};
	while ( parent.has_parent_path() ){
		if ( parent.filename().string() == "build" ){
			return check();
		}
		/* go one further up */
		parent = parent.parent_path();
	}
	return false;

}

int main(int argc, char* const argv[])
{
	/* get working directory directly at startup, before
	 * other programs might have changed it */
	const fs::path currentPath { fs::current_path() };

	/* create logger with default settings */
	std::shared_ptr<spdlog::logger> logger { hms::log::createLogger( {} ) };
	logger->set_level(hms::log::Level::err);

    Catch::Session session;
	// Build a new parser on top of Catch's
	using namespace Catch::Clara;
	auto cli 
	= session.cli() // Get Catch's composite command line parser
		| Opt( globalVar::testDir, "testDir" )      // bind variable to a new option, with a hint string
		["-p"]["--testDir"]                         // the option names it will respond to
		("Full path of the test source directory"); // description string for the help output
		
	// Now pass the new composite back to Catch so it uses that
	session.cli( cli ); 

	// Let Catch (using Clara) parse the command line
	int returnCode = session.applyCommandLine( argc, argv );
	if( returnCode != 0 ) // Indicates a command line error
		return returnCode;

	if ( globalVar::testDir.empty() ){
		if ( !testDirFound(currentPath) ){
			std::cout << "Please provide source directory of tests with option \"--testDir\".\n";
			return 1;
		}
	}

    return session.run();
}